home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------*/
- /* FILE: zreceive.c (Opus zmodem receiver) */
- /* */
- /* */
- /* The Opus Computer-Based Conversation System */
- /* (c) Copyright 1986, Wynn Wagner III, All Rights Reserved */
- /* */
- /* This implementation of Chuck Forsberg's ZMODEM protocol was */
- /* for Opus by Rick Huebner and Wynn Wagner III */
- /* */
- /* (MSC/4 with /Zp /Ox) */
- /* */
- /* */
- /* */
- /* */
- /* This module is similar to a routine used by Opus-Cbcs (1.00). It is */
- /* provided for your information only. You will find routines that need */
- /* to be coded and identifiers to be resolved. */
- /* */
- /* There is absolutely no guarantee that anything here will work. If you */
- /* break this routine, you own both pieces. */
- /* */
- /* USAGE: You may use this material in any program with no obligation */
- /* as long as there is no charge for your program. For more */
- /* information about commercial use, contact the "OPUSinfo HERE" */
- /* BBS (124/111). */
- /* */
- /* NOTE: There are a couple of things the Opus implementation does that */
- /* aren't part of the original ZModem protocol. They all deal */
- /* with WaZOO type ("ZedZap") netmail and should only show up when */
- /* used under that condition. */
- /* */
- /* * The maximum packet size can grow larger than 1k. It is */
- /* sensitive to the baud rate. (2400b=2048k; 9600b=8192k) */
- /* * The sender must be able to send nothing. In other words, */
- /* the sending system must be able to initiate and terminate */
- /* a zmodem send session without having to actually send a */
- /* file. Normally this kind of thing would never happen in */
- /* zmodem. */
- /* */
- /* */
- /*--------------------------------------------------------------------------*/
- #include "zmodem.h"
- #include "com.h"
- #include <sys/utime.h>
-
- /*--------------------------------------------------------------------------*/
- /* External material */
- /*--------------------------------------------------------------------------*/
- extern int dexists(byte *);
- extern long zfree (char *);
-
- extern int got_arcmail;
- extern int got_bundle;
- extern int remote_capabilities;
- extern int got_mail;
- extern int overwrite;
- extern int un_attended;
- extern int fullscreen;
-
-
- /*--------------------------------------------------------------------------*/
- /* Local routines */
- /*--------------------------------------------------------------------------*/
- int cdecl get_Zmodem(byte *,FILE *);
-
- static int pascal RZ_ReceiveData(byte *,int );
- static int pascal RZ_InitReceiver(void);
- static int pascal RZ_ReceiveBatch(FILE *);
- static int pascal RZ_ReceiveFile(FILE *);
- static int pascal RZ_GetHeader(void);
- static void pascal unique_name(byte *);
- static int pascal RZ_SaveToDisk(unsigned long *);
- static void pascal RZ_AckBibi(void);
-
-
- /*--------------------------------------------------------------------------*/
- /* Private declarations */
- /*--------------------------------------------------------------------------*/
- static long DiskAvail;
- static long filetime;
- static byte realname[64];
-
- /*--------------------------------------------------------------------------*/
- /* Private data */
- /*--------------------------------------------------------------------------*/
-
- /* Parameters for ZSINIT frame */
- #define ZATTNLEN 32 /* Max length of attention string */
-
- static char Attn[ZATTNLEN+1]; /* String rx sends to tx on err */
- static FILE *Outfile; /* Handle of file being received */
- static byte *Secbuf; /* Pointer to receive buffer */
- static int Tryzhdrtype; /* Hdr type to send for Last rx close */
- static char isBinary; /* Current file is binary mode */
- static char EOFseen; /* indicates cpm eof (^Z) was received */
- static char Zconv; /* ZMODEM file conversion request */
- static int RxCount; /* Count of data bytes received */
- static byte Resume_WaZOO; /* Flags resumption of aborted WaZOO xfer */
- static byte Resume_name[13]; /* "Real" name of file being received */
- static byte Resume_info[48]; /* File size&time info for rx file */
- static byte Abortlog_name[PATHLEN]; /* Path of WaZOO aborted xfer log */
- static byte Upload_path[PATHLEN]; /* Dest. path of file being received */
- static long Filestart; /* File offset we started this xfer from */
- extern long filelength(); /* returns length of file ref'd in stream */
-
-
-
- /*--------------------------------------------------------------------------*/
- /* GET ZMODEM */
- /* Receive a batch of files. */
- /* returns TRUE (1) for good xfer, FALSE (0) for bad */
- /* can be called from f_upload or to get mail from a WaZOO Opus */
- /*--------------------------------------------------------------------------*/
- int cdecl get_Zmodem(rcvpath, xferinfo)
- byte *rcvpath;
- FILE *xferinfo;
- begin
- byte namebuf[PATHLEN];
- int i;
- byte *p;
-
- if (un_attended && fullscreen)
- gotoxy (0,13);
-
- filetime = 0;
- errno = 0;
-
- _BRK_DISABLE();
- XON_ENABLE();
- n_disable();
-
- Secbuf = NULL;
- Outfile = NULL;
- z_size = 0;
-
- DiskAvail = zfree("");
-
- Rxtimeout = 100;
- Tryzhdrtype = ZRINIT;
- Secbuf = zalloc();
-
- strcpy(namebuf, rcvpath);
- Filename = namebuf;
-
- strcpy(Upload_path,rcvpath);
- p = Upload_path+strlen(Upload_path)-1;
- while (p>=Upload_path && *p!='\\') --p;
- *(++p) = '\0';
-
- sprintf(Abortlog_name, "%s%04x%04x.Z\0",
- ctl.hold_area,remote_net,remote_node);
-
- if (((i=RZ_InitReceiver())==ZCOMPL) or
- ((i==ZFILE) and ((RZ_ReceiveBatch(xferinfo))==OK)) )
- begin
- free(Secbuf);
- return 1;
- end
-
- CLEAR_OUTBOUND();
- send_can(); /* transmit at least 10 cans */
- wait_for_clear();
-
- if (Secbuf) free(Secbuf);
- if (Outfile) fclose(Outfile);
- return 0;
-
- end /* get_Zmodem */
-
-
-
-
-
- /*--------------------------------------------------------------------------*/
- /* RZ RECEIVE DATA */
- /* Receive array buf of max length with ending ZDLE sequence */
- /* and CRC. Returns the ending character or error code. */
- /*--------------------------------------------------------------------------*/
- static int pascal RZ_ReceiveData(buf, length)
- register byte *buf;
- register int length;
- begin
- register int c;
- register word crc;
- int d;
-
- crc = RxCount = 0;
- buf[0] = buf[1] = 0;
-
- while(1)
- begin
- if ((c = Z_GetZDL()) & ~0xFF)
- begin
- CRCfoo:
- switch (c)
- begin
- case GOTCRCE:
- case GOTCRCG:
- case GOTCRCQ:
- case GOTCRCW: /*-----------------------------------*/
- /* C R C s */
- /*-----------------------------------*/
- crc = Z_UpdateCRC(((d=c)&0xFF), crc);
- if ((c=Z_GetZDL()) & ~0xFF) goto CRCfoo;
-
- crc = Z_UpdateCRC(c, crc);
- if ((c=Z_GetZDL()) & ~0xFF) goto CRCfoo;
-
- crc = Z_UpdateCRC(c, crc);
- if (crc & 0xFFFF)
- begin
- z_message( CRC_msg );
- return ERROR;
- end
- return d;
-
- case GOTCAN: /*-----------------------------------*/
- /* Cancel */
- /*-----------------------------------*/
- z_log(Cancelled_msg);
- return ZCAN;
-
- case TIMEOUT: /*-----------------------------------*/
- /* Timeout */
- /*-----------------------------------*/
- z_message( TIME_msg );
- return c;
-
- case RCDO: /*-----------------------------------*/
- /* No carrier */
- /*-----------------------------------*/
- z_log( CARRIER_msg );
- return c;
-
- default: /*-----------------------------------*/
- /* Something bizarre */
- /*-----------------------------------*/
- z_message("Debris");
- cprintf(" [%x]",c);
- CLEAR_INBOUND();
- return c;
- end /* switch */
- end /* if */
-
- if (--length < 0)
- begin
- z_message("Long pkt");
- return ERROR;
- end
-
- ++RxCount;
- *buf++ = c;
- crc = Z_UpdateCRC(c, crc);
- continue;
- end /* while(1) */
-
- end /* RZ_ReceiveData */
-
-
-
- /*--------------------------------------------------------------------------*/
- /* RZ INIT RECEIVER */
- /* Initialize for Zmodem receive attempt, try to activate Zmodem sender */
- /* Handles ZSINIT, ZFREECNT, and ZCOMMAND frames */
- /* */
- /* Return codes: */
- /* ZFILE .... Zmodem filename received */
- /* ZCOMPL ... transaction finished */
- /* ERROR .... any other condition */
- /*--------------------------------------------------------------------------*/
- static int pascal RZ_InitReceiver()
- begin
- register int n;
- int errors = 0;
- char *sptr;
-
-
- for (n=10; --n>=0; )
- begin
-
- /*--------------------------------------------------------------*/
- /* Set buffer length (0=unlimited, don't wait). */
- /* Also set capability flags */
- /*--------------------------------------------------------------*/
- Z_PutLongIntoHeader(0L);
- Txhdr[ZF0] = CANFDX|CANOVIO;
- Z_SendHexHeader(Tryzhdrtype, Txhdr);
- if (Tryzhdrtype == ZSKIP) Tryzhdrtype = ZRINIT;
-
- AGAIN:
-
- switch (Z_GetHeader(Rxhdr))
- begin
- case ZFILE: /*-----------------------------------------*/
- /* */
- /*-----------------------------------------*/
- Zconv = Rxhdr[ZF0];
- Tryzhdrtype = ZRINIT;
- if (RZ_ReceiveData(Secbuf,WAZOOMAX)==GOTCRCW)
- return ZFILE;
- Z_SendHexHeader(ZNAK, Txhdr);
- goto AGAIN;
-
- case ZSINIT: /*-----------------------------------------*/
- /* */
- /*-----------------------------------------*/
- if (RZ_ReceiveData(Attn, ZATTNLEN) == GOTCRCW)
- Z_SendHexHeader(ZACK, Txhdr);
- else Z_SendHexHeader(ZNAK, Txhdr);
- goto AGAIN;
-
- case ZFREECNT: /*-----------------------------------------*/
- /* */
- /*-----------------------------------------*/
- Z_PutLongIntoHeader(DiskAvail);
- Z_SendHexHeader(ZACK, Txhdr);
- goto AGAIN;
-
- case ZCOMMAND: /*-----------------------------------------*/
- /* Paranoia is good for you... */
- /* Ignore command from remote, but lie and */
- /* say we did the command ok. */
- /*-----------------------------------------*/
- if (RZ_ReceiveData(Secbuf,WAZOOMAX)==GOTCRCW)
- begin
- status_line("!Ignoring `%s'", Secbuf);
- Z_PutLongIntoHeader(0L);
- do
- begin
- Z_SendHexHeader(ZCOMPL, Txhdr);
- end
- while (++errors<10 && Z_GetHeader(Rxhdr) != ZFIN);
- RZ_AckBibi();
- return ZCOMPL;
- end
- else Z_SendHexHeader(ZNAK, Txhdr);
- goto AGAIN;
-
- case ZCOMPL: /*-----------------------------------------*/
- /* */
- /*-----------------------------------------*/
- goto AGAIN;
-
- case ZFIN: /*-----------------------------------------*/
- /* */
- /*-----------------------------------------*/
- RZ_AckBibi();
- return ZCOMPL;
-
- case ZCAN: sptr = CAN_msg;
- goto Err;
-
- case RCDO: sptr = CARRIER_msg;
- goto Err;
-
- end /* switch */
-
- end /* for */
-
- sptr = TIME_msg;
-
- Err:
- sprintf(e_input,"!Z-InitRecv %s",sptr);
- z_log(e_input);
-
- return ERROR;
-
- end /* RZ_InitReceiver */
-
-
-
-
- /*--------------------------------------------------------------------------*/
- /* RZFILES */
- /* Receive a batch of files using ZMODEM protocol */
- /*--------------------------------------------------------------------------*/
- static int pascal RZ_ReceiveBatch(xferinfo)
- FILE *xferinfo;
- begin
- register int c;
- FILE *abortlog;
- FILE *newlog;
- byte linebuf[64];
- byte namebuf[PATHLEN];
- byte *p;
-
- /* set_xy("");*/
- while(1)
- begin
- switch (c = RZ_ReceiveFile(xferinfo))
- begin
- case ZEOF:
- if (Resume_WaZOO) {
- errno = 0;
- abortlog = fopen(Abortlog_name, read_ascii);
- if (!got_error(OPEN_msg,Abortlog_name)) {
- strcpy(namebuf,Abortlog_name);
- strcpy(namebuf+strlen(namebuf)-1,"TMP");
- errno = c = 0;
- newlog = fopen(namebuf, write_ascii);
- if (!got_error(OPEN_msg,namebuf)) {
- while (!feof(abortlog)) {
- linebuf[0] = '\0';
- if (!fgets(linebuf,64,abortlog)) break;
- p = linebuf;
- while (*p > ' ') ++p;
- *p = '\0';
- if (stricmp(linebuf,Resume_name)) {
- *p = ' ';
- fputs(linebuf,newlog);
- ++c;
- }
- }
- fclose(abortlog);
- fclose(newlog);
- unlink(Abortlog_name);
- if (c) rename(namebuf,Abortlog_name);
- else unlink(namebuf);
- } else fclose(abortlog);
- }
- strcpy(namebuf,Upload_path);
- strcat(namebuf,Resume_name);
- unique_name(namebuf);
- rename(Filename,namebuf);
- }
- /* fallthrough */
- case ZSKIP:
- switch (RZ_InitReceiver())
- begin
- case ZCOMPL: return OK;
- default: return ERROR;
- case ZFILE: break;
- end /* switch */
- break;
-
- default:
- fclose(Outfile);
- Outfile = NULL;
- if (remote_capabilities) {
- if (!Resume_WaZOO) {
- strcpy(namebuf,Upload_path);
- strcat(namebuf,"BadWaZOO.001");
- unique_name(namebuf);
- rename(Filename,namebuf);
- errno = 0;
- abortlog = fopen(Abortlog_name, "at");
- if (!got_error(OPEN_msg,Abortlog_name)) {
- fprintf(abortlog, "%s %s %s\n",
- Resume_name,
- namebuf+strlen(Upload_path),
- Resume_info);
- fclose(abortlog);
- } else unlink(namebuf);
- }
- } else unlink(Filename);
- errno = 0;
- return c;
- end /* switch */
-
- end /* while */
-
- end /* RZ_ReceiveBatch */
-
-
-
-
- /*--------------------------------------------------------------------------*/
- /* RZ RECEIVE FILE */
- /* Receive one file; assumes file name frame is preloaded in Secbuf */
- /*--------------------------------------------------------------------------*/
- static int pascal RZ_ReceiveFile(xferinfo)
- FILE *xferinfo;
- begin
- register int c;
- int n;
- long rxbytes;
- char *sptr;
- struct utimbuf utimes;
-
- EOFseen=FALSE;
- if (RZ_GetHeader() == ERROR) return (Tryzhdrtype = ZSKIP);
-
- n = 10;
- rxbytes = Filestart;
-
- while(1)
- begin
- Z_PutLongIntoHeader(rxbytes);
- Z_SendHexHeader(ZRPOS, Txhdr);
- NxtHdr:
- switch (c = Z_GetHeader(Rxhdr))
- begin
- case ZDATA: /*-----------------------------------------*/
- /* Data Packet */
- /*-----------------------------------------*/
- if (Rxpos != rxbytes)
- begin
- if ( --n < 0)
- begin
- sptr = FUBAR_msg;
- goto Err;
- end
- z_message(NULL);
- cprintf("Bad pos; %ld/%ld",rxbytes,Rxpos);
- Z_PutString(Attn);
- continue;
- end
- MoreData:
- switch (c = RZ_ReceiveData(Secbuf,WAZOOMAX))
- begin
- case ZCAN: sptr = Cancelled_msg;
- goto Err;
-
- case RCDO: sptr = CARRIER_msg;
- goto Err;
-
- case ERROR: /*-----------------------*/
- /* CRC error */
- /*-----------------------*/
- if (--n<0)
- begin
- sptr = FUBAR_msg;
- goto Err;
- end
- show_loc(rxbytes,n);
- Z_PutString(Attn);
- continue;
-
- case TIMEOUT: /*---------------------*/
- /* */
- /*-----------------------*/
- if (--n<0)
- begin
- sptr = TIME_msg;
- goto Err;
- end
- show_loc(rxbytes,n);
- continue;
-
- case GOTCRCW: /*---------------------*/
- /* End of frame */
- /*-----------------------*/
- n = 10;
- if (RZ_SaveToDisk(&rxbytes)==ERROR)
- return ERROR;
- Z_PutLongIntoHeader(rxbytes);
- Z_SendHexHeader(ZACK, Txhdr);
- goto NxtHdr;
-
- case GOTCRCQ: /*---------------------*/
- /* Zack expected */
- /*-----------------------*/
- n = 10;
- if (RZ_SaveToDisk(&rxbytes)==ERROR)
- return ERROR;
- Z_PutLongIntoHeader(rxbytes);
- Z_SendHexHeader(ZACK, Txhdr);
- goto MoreData;
-
- case GOTCRCG: /*---------------------*/
- /* Non-stop */
- /*-----------------------*/
- n = 10;
- if (RZ_SaveToDisk(&rxbytes)==ERROR)
- return ERROR;
- goto MoreData;
-
- case GOTCRCE: /*---------------------*/
- /* Header to follow */
- /*-----------------------*/
- n = 10;
- if (RZ_SaveToDisk(&rxbytes)==ERROR)
- return ERROR;
- goto NxtHdr;
- end /* switch */
-
- case ZNAK:
- case TIMEOUT: /*-----------------------------------------*/
- /* Packed was probably garbled */
- /*-----------------------------------------*/
- if ( --n < 0)
- begin
- sptr = "Garbled packet";
- goto Err;
- end
- show_loc(rxbytes,n);
- continue;
-
- case ZFILE: /*-----------------------------------------*/
- /* Sender didn't see our ZRPOS yet */
- /*-----------------------------------------*/
- RZ_ReceiveData(Secbuf, WAZOOMAX);
- continue;
-
- case ZEOF: /*-----------------------------------------*/
- /* End of the file */
- /* Ignore EOF if it's at wrong place; force*/
- /* a timeout because the eof might have */
- /* gone out before we sent our ZRPOS */
- /*-----------------------------------------*/
- if (locate_y) gotoxy(0,(byte)locate_y-1);
- if (Rxpos != rxbytes) goto NxtHdr;
-
- throughput(2,rxbytes-Filestart);
- errno = 0;
-
- fclose(Outfile);
- got_error(CLOSE_msg,Filename);
-
- status_line("+Received-Z %s",realname);
-
- if (filetime)
- begin
- utimes.actime = filetime;
- utimes.modtime = filetime;
- utime (Filename, &utimes);
- end
-
- Outfile = NULL;
- if (xferinfo != NULL)
- begin
- fprintf(xferinfo, "%s\n", Filename);
- got_error(WRITE_msg,"XferInfo");
- end
- return c;
-
- case ERROR: /*-----------------------------------------*/
- /* Too much garbage in header search error */
- /*-----------------------------------------*/
- if ( --n < 0)
- begin
- sptr = "HdrJunk";
- goto Err;
- end
- show_loc(rxbytes,n);
- Z_PutString(Attn);
- continue;
-
- default: /*-----------------------------------------*/
- /* */
- /*-----------------------------------------*/
- sptr = IDUNNO_msg;
- goto Err;
-
- end /* switch */
-
- end /* while */
-
- Err: sprintf(e_input,"!Z-rz %s",sptr);
- z_log(e_input);
- return ERROR;
-
- end /* RZ_ReceiveFile */
-
-
-
- /*--------------------------------------------------------------------------*/
- /* RZ GET HEADER */
- /* Process incoming file information header */
- /*--------------------------------------------------------------------------*/
- static int pascal RZ_GetHeader()
- begin
-
- register byte *p, *q;
- register int n;
- int i;
-
- byte *ourname;
- byte *theirname;
- unsigned long filesize;
- byte *fileinfo;
- FILE *abortlog;
- byte linebuf[64];
- byte *badfile_name;
- char *strchr();
-
- /*--------------------------------------------------------------------*/
- /* Setup the transfer mode */
- /*--------------------------------------------------------------------*/
- isBinary = (!RXBINARY && Zconv == ZCNL)? 0 : 1;
- Resume_WaZOO = 0;
-
-
- /*--------------------------------------------------------------------*/
- /* Extract and verify filesize, if given. */
- /* Reject file if not at least 10K free */
- /*--------------------------------------------------------------------*/
- filesize = 0L;
- fileinfo = Secbuf + 1 + strlen(Secbuf);
- if (*fileinfo) sscanf(fileinfo, "%ld %lo", &filesize, &filetime);
- if (filesize+10240 > DiskAvail)
- begin
- status_line("!Disk space");
- return ERROR;
- end
-
- /*--------------------------------------------------------------------*/
- /* Get and/or fix filename for uploaded file */
- /*--------------------------------------------------------------------*/
- p = Filename+strlen(Filename)-1; /* Find end of Opus upload path */
- while (p>=Filename && *p!='\\') p--;
- ourname = ++p;
-
- p = Secbuf+strlen(Secbuf)-1; /* Find transmitted simple filename */
- while (p >= Secbuf && *p!='\\' && *p!='/' && *p!=':') p--;
- theirname = ++p;
-
-
- strcpy(ourname,theirname); /* Start w/ our path & their name */
- strcpy(realname,Filename);
-
- /*--------------------------------------------------------------------*/
- /* Save info on WaZOO transfer in case of abort */
- /*--------------------------------------------------------------------*/
- if (remote_capabilities) {
- strcpy(Resume_name,theirname);
- strcpy(Resume_info,fileinfo);
- }
-
- /*--------------------------------------------------------------------*/
- /* Check if this is a failed WaZOO transfer which should be resumed */
- /*--------------------------------------------------------------------*/
- if (remote_capabilities && dexists(Abortlog_name))
- begin
- errno = 0;
- abortlog = fopen( Abortlog_name, read_ascii );
- if (!got_error(OPEN_msg,Abortlog_name))
- begin
- while (!feof(abortlog))
- begin
- linebuf[0] = '\0';
- if (!fgets( (p=linebuf), 64, abortlog)) break;
- while (*p >= ' ') ++p;
- *p = '\0';
- p = strchr(linebuf,' ');
- *p = '\0';
- if (!stricmp(linebuf,theirname))
- begin
- p = strchr( (badfile_name = ++p), ' ');
- *p = '\0';
- if (!stricmp(++p,fileinfo))
- begin
- Resume_WaZOO = 1;
- break;
- end
- end
- end
- fclose(abortlog);
- end
- end
-
- /*--------------------------------------------------------------------*/
- /* Open either the old or a new file, as appropriate */
- /*--------------------------------------------------------------------*/
- if (Resume_WaZOO)
- begin
- strcpy(ourname,badfile_name);
- p = "r+b";
- end
- else
- begin
- strcpy(ourname,theirname);
- if (dexists(Filename))
- begin /* If file already exists... */
- i = strlen (Filename) - 1;
- if ((!overwrite) || (is_arcmail (Filename, i)))
- begin
- unique_name(Filename);
- end
- else
- begin
- unlink (Filename);
- end
- end /* if exist */
-
- if (strcmp(ourname,theirname))
- begin
- status_line("+Dupe renamed: %s",ourname);
- set_xy(NULL);
- end
- p = write_binary;
- end
- errno = 0;
- Outfile = fopen( Filename, p);
- if (got_error(OPEN_msg,Filename)) return ERROR;
-
- Filestart = (Resume_WaZOO)? filelength(fileno(Outfile)): 0L;
- fseek(Outfile, Filestart, SEEK_SET);
-
-
- if (remote_capabilities)
- begin
- p = theirname;
- n = strlen(p)-1;
-
- if ((p[n]=='t')&&(p[n-1]=='k')&&(p[n-2]=='p')&&(p[n-3]=='.'))
- begin
- got_bundle = 1;
- got_mail = 1;
- p = "Bundle ";
- end
- else if (is_arcmail (p, n))
- begin
- got_mail = 1;
- p = "LZ-mail ";
- end
- else
- begin
- got_mail = 1;
- p = "NetFile ";
- end
- end
- else p = NULL;
-
- if (un_attended && fullscreen)
- {
- clear_filetransfer();
- gotoxy (0,13);
- }
- else
- {
- set_xy (NULL);
- }
- cprintf("%s %s; %s%ldb, %d min.",
- (p)? p: "Receiving",
- realname,
- (isBinary)? "": "ASCII ",
- filesize,
- (int)(filesize*10/cur_baud+27)/54);
-
- set_xy(NULL);
-
- throughput(0,0L);
-
- return OK;
-
- end /* RZ_GetHeader */
-
-
- /*--------------------------------------------------------------------------*/
- /* UNIQUE_NAME */
- /* Increments the suffix of a filename as necessary to make the name unique */
- /*--------------------------------------------------------------------------*/
- static void pascal unique_name(fname)
- byte *fname;
- begin
- static byte suffix[] = ".001";
- register char *p;
- register int n;
-
- if (dexists(fname))
- begin /* If file already exists... */
- p = fname;
- while (*p && *p!='.') p++; /* ...find the extension, if any */
- for (n=0; n<4; n++) /* ...fill it out if neccessary */
- if (!*p)
- begin
- *p = suffix[n];
- *(++p) = '\0';
- end
- else p++;
-
- while (dexists(fname)) /* ...If 'file.ext' exists suffix++ */
- begin
- p = fname+strlen(fname)-1;
- for (n=3; n--;)
- begin
- if (!isdigit(*p)) *p = '0';
- if (++(*p) <= '9') break;
- else *p-- = '0';
- end /* for */
- end /* while */
- end /* if exist */
- end /* unique_name */
-
-
- /*--------------------------------------------------------------------------*/
- /* RZ SAVE TO DISK */
- /* Writes the received file data to the output file. */
- /* If in ASCII mode, stops writing at first ^Z, and converts all */
- /* solo CR's or LF's to CR/LF pairs. */
- /*--------------------------------------------------------------------------*/
- static int pascal RZ_SaveToDisk(rxbytes)
- unsigned long *rxbytes;
- begin
- static byte lastsent;
-
- register byte *p;
- register int count;
-
- count = RxCount;
-
- if (((KEYPRESS()) and (READKB()==27)))
- begin
- send_can(); /* Cancel file */
- while (Z_GetByte(20)!=TIMEOUT) /* Wait for line to clear */
- ;
- send_can(); /* and Cancel Batch */
- z_log( KBD_msg );
- return ERROR;
- end
-
- if (count!=z_size)
- begin
- gotoxy( locate_x+10, locate_y );
- cputs( ultoa(((unsigned long )(z_size=count)),e_input,10) );
- putch(' ');
- end
-
- errno = 0;
-
- if (isBinary)
- begin
- fwrite( Secbuf, count, 1, Outfile );
- if (errno) goto oops;
- end
- else
- begin
- if (EOFseen) return OK;
- for (p=Secbuf; --count>=0; ++p )
- begin
- if ( *p == CPMEOF)
- begin
- EOFseen = TRUE;
- return OK;
- end
- if ( *p=='\n' ) {
- if (lastsent!='\r' && putc('\r', Outfile) == EOF)
- goto oops;
- } else {
- if (lastsent=='\r' && putc('\n', Outfile) == EOF)
- goto oops;
- }
- if (putc((lastsent=*p), Outfile) == EOF) goto oops;
- end
- end
-
- *rxbytes += RxCount;
-
- gotoxy( locate_x, locate_y );
- cputs( ultoa(((unsigned long )(*rxbytes)),e_input,10) );
- return OK;
-
- oops:
- got_error(WRITE_msg,Filename);
- return ERROR;
-
- end /* RZ_SaveToDisk */
-
-
-
- /*--------------------------------------------------------------------------*/
- /* RZ ACK BIBI */
- /* Ack a ZFIN packet, let byegones be byegones */
- /*--------------------------------------------------------------------------*/
- static void pascal RZ_AckBibi()
- begin
- register int n;
-
- Z_PutLongIntoHeader(0L);
- for (n=4; --n;)
- begin
- Z_SendHexHeader(ZFIN, Txhdr);
- switch (Z_GetByte(100))
- begin
- case 'O': Z_GetByte(1); /* Discard 2nd 'O' */
-
- case TIMEOUT:
- case RCDO: return;
- end /* switch */
- end /* for */
-
- end /* RZ_AckBibi */
-